package com.eascs.p2p.investor.server.impl;

import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.eascs.app.dao.PageResult;
import com.eascs.app.log.Logger;
import com.eascs.app.log.LoggerFactory;
import com.eascs.p2p.admin.manager.IInvestObjectManager;
import com.eascs.p2p.admin.service.impl.InvestObjectServiceImpl;
import com.eascs.p2p.common.entity.InvestObjExtEntity;
import com.eascs.p2p.common.entity.InvestObjectEntity;
import com.eascs.p2p.common.entity.InvestorEntity;
import com.eascs.p2p.common.entity.InvestorRecordEntity;
import com.eascs.p2p.common.entity.InvestorWalletEntity;
import com.eascs.p2p.common.entity.InvestorWalletFlowEntity;
import com.eascs.p2p.common.vo.InvestorVO;
import com.eascs.p2p.common.vo.ModelResult;
import com.eascs.p2p.common.wallet.common.TransType;
import com.eascs.p2p.common.wallet.utils.BigDecimalUtils;
import com.eascs.p2p.investor.dao.InvestorDao;
import com.eascs.p2p.investor.server.InvestorServiceInner;
import com.eascs.p2p.wallet.dao.InvestorWalletDao;
@Service
public class InvestorServiceInnerImpl implements InvestorServiceInner {
	private static Logger logger = LoggerFactory.getLogger(InvestorServiceInnerImpl.class);
	@Autowired
	private InvestorDao investorDao;
	@Autowired
	private InvestorWalletDao investorWalletDao;
	@Autowired 	
	private IInvestObjectManager investObjectManager;
	@Autowired
	private InvestObjectServiceImpl investObjectService;
	@Override
	public ModelResult<InvestorEntity> queryInvestor(InvestorEntity investor) {
		ModelResult<InvestorEntity> result = new ModelResult<>();
		try {
			InvestorEntity vo = investorDao.queryInvestor(investor);
			result.withModel(vo);
		} catch (Exception e) {
			logger.error("获取投资者失败, account:{}, password:{}", investor.getAccount(), investor.getPassword());
			result.withError("InvestorServiceInnerImpl.queryInvestor", "获取投资者失败");
			e.printStackTrace();
			return result;
		}
		return result;
	}

	@Override
	@Transactional(transactionManager = "transactionManager")
	public ModelResult<Boolean> register(InvestorEntity investor) {
		ModelResult<Boolean> result = new ModelResult<>();
		try {
			Date currData = new Date();
			investor.setCreateTime(currData);
			investor.setUpdateTime(currData);
			InvestorEntity entity = investorDao.queryInvestorByAccount(investor.getAccount());
			if(entity != null){
				logger.error("注册失败,用户账号已存在,account:[{}]", investor.getAccount());
				return result.withError("InvestorServiceInnerImpl.register", "注册失败,用户账号已存在");
			}
			investor = investorDao.insertInvestor(investor);
			if (!investor.getId().isEmpty()) {
				InvestorWalletEntity investorWallet = new InvestorWalletEntity(true);
				investorWallet.setInvestorId(investor.getId());
				investorWallet.setCreateTime(currData);
				investorWallet.setUpdateTime(currData);
				investorWalletDao.insertInvestorWallet(investorWallet);
			}
			
		} catch (Exception e) {
			logger.error("注册失败, account:{}, error:{}", investor.getAccount(), e.getMessage());
			result.withError("InvestorServiceInnerImpl.register", "注册失败");
			e.printStackTrace();
			return result;
		}
		result.withModel(true);
		return result;
	}

	@Override
	public ModelResult<List<InvestorRecordEntity>> queryInvestorRecordList(InvestorRecordEntity investorRecord) {
		ModelResult<List<InvestorRecordEntity>> result = new ModelResult<>();
		try {
			List<InvestorRecordEntity> list = investorDao.queryInvestorRecordList(investorRecord);
			result.withModel(list);
		} catch (Exception e) {
			e.printStackTrace();
			return result;
		}
		return result;
	}

	@Override
	@Transactional(transactionManager = "transactionManager")
	public ModelResult<Boolean> buyInvest(InvestorEntity investor, String investObjId, BigDecimal investMoney) {
		ModelResult<Boolean> result = new ModelResult<>();
		if (investor == null || investObjId.isEmpty() || investMoney == null) {
			logger.error("下单失败，参数为空, investor:{}, investObjId:{}, investMoney:{}", investor, investObjId,
					investMoney);
			return result.withError("InvestorServiceInnerImpl.buyInvest", "下单失败，参数为空");
		}
		if (investor.getIsRealname() == InvestorEntity.IS_REALNAME_NO) {
			logger.error("下单失败，用户未实名认证, account:{}", investor.getAccount());
			return result.withError("InvestorServiceInnerImpl.buyInvest", "下单失败，用户未实名认证");
		}
		InvestorWalletEntity investorWallet = investorWalletDao.queryInvestorWallet(investor.getId());
		if (investorWallet == null) {
			logger.error("下单失败，无法获取用户钱包, account:{}", investor.getAccount());
			return result.withError("InvestorServiceInnerImpl.buyInvest", "下单失败，无法获取用户钱包");
		}
		if (investorWallet != null && investorWallet.getCurrentBalance().compareTo(investMoney) == -1) {
			logger.error("下单失败，用户余额不足, account:{}", investor.getAccount());
			return result.withError("InvestorServiceInnerImpl.buyInvest", "下单失败，用户余额不足");
		}
		ModelResult<InvestObjectEntity> investObjModelResult = investObjectService
				.findInvestObjectDetail(investObjId);
		if (!investObjModelResult.isSuccess() || investObjModelResult.getModel() == null) {
			logger.error("下单失败，无法获取标的信息, investObjId:{}", investObjId);
			return result.withError("InvestObjectServiceImpl.findInvestObjectDetail", "下单失败，无法获取标的信息");
		}
		InvestObjectEntity investObject = investObjModelResult.getModel();
		if (investObject.getObjectStatus() != InvestObjectEntity.OBJ_STATUS_PUBLISH) {
			logger.error("下单失败，标的状态必须为发布中的，investObjId:{},investObjName:{}", investObjId, investObject.getTitle());
			return result.withError("InvestorServiceInnerImpl.buyInvest", "下单失败，标的状态必须为发布中的");
		}
		if (investMoney.compareTo(investObject.getLowestInvestentAmount()) == -1) {
			logger.error("下单失败，最低投资金额为:{}",
					investObject.getLowestInvestentAmount().setScale(2, BigDecimal.ROUND_HALF_UP));
			return result.withError("InvestorServiceInnerImpl.buyInvest", "下单失败，未超过最低投资金额");
		}
		if (investObject.getInvestedAmount().compareTo(investObject.getLoanAmount()) == 1
				|| (investObject.getInvestedAmount().add(investMoney))
						.compareTo(investObject.getLoanAmount()) == 1) {
			logger.error("下单失败，投资金额超过该标的上限,已投金额:{},下单金额:{},标的预期借款金额：{}",
					investObject.getInvestedAmount().setScale(2, BigDecimal.ROUND_HALF_UP),
					investMoney.setScale(2, BigDecimal.ROUND_HALF_UP),
					investObject.getLoanAmount().setScale(2, BigDecimal.ROUND_HALF_UP));
			return result.withError("InvestorServiceInnerImpl.buyInvest", "下单失败，投资金额超过该标的上限");
		}
		walletHandle(investorWallet, investor, investObject, investMoney);
		// 满额
		if ((investObject.getInvestedAmount()).compareTo(investObject.getLoanAmount()) == 0) {
			investObjectFull(investObject, investMoney);
		}
		result.setModel(true);
		return result;
	}

	/**
	 * 标的满额
	 * @param investObject 标的对象
	 * @param investMoney  投资金额
	 */
	private void investObjectFull(InvestObjectEntity investObject, BigDecimal investMoney){
		Date curDate = new Date();
		// 更改标的状态
		InvestObjectEntity object=	investObjectManager.findInvestObjectDetail(investObject.getId());
		object.setObjectStatus(InvestObjectEntity.OBJ_STATUS_FULL);
		object.setObjectFulfill(curDate);
		ModelResult<InvestObjExtEntity> ext=	investObjectService.findInvestObjExtEntityDetail(investObject.getId());
		ModelResult<Boolean> modelResult = investObjectService.updateInvestObjectEntity(object,ext.getModel());
		if (!modelResult.isSuccess() || !modelResult.getModel()) {
			throw new RuntimeException("下单失败");
		}
		// 钱包、流水【标的的所有投资用户】
		List<InvestorRecordEntity> recordlist = investorDao.queryInvestorRecordListByInvestObjId(investObject.getId());
		BigDecimal rateYield = investObject.getAnnualizedYield();// 年化收益率
		BigDecimal deadline = investObject.getAnnualizedYield();// 期限
		InvestorWalletEntity wallet = null;
		for (InvestorRecordEntity record : recordlist) {
			wallet = investorWalletDao.queryInvestorWallet(record.getInvestorId());
			if (wallet == null) {
				throw new RuntimeException("下单失败");
			}
			BigDecimal investFrozen = wallet.getInvestFrozen().subtract(record.getInvestAmount()).setScale(2,
					BigDecimal.ROUND_HALF_UP);
			BigDecimal awaitPrincipal = wallet.getAwaitPrincipal().add(record.getInvestAmount()).setScale(2,
					BigDecimal.ROUND_HALF_UP);
			BigDecimal income = BigDecimalUtils.incomeHandle(record.getInvestAmount(), rateYield, deadline, investObject.getDeadlineType());
			BigDecimal awaitIncome = wallet.getAwaitIncome().add(income).setScale(2, BigDecimal.ROUND_HALF_UP);
			wallet.setInvestFrozen(investFrozen);
			wallet.setUpdateTime(curDate);
			wallet.setAwaitPrincipal(awaitPrincipal);
			wallet.setAwaitIncome(awaitIncome);
			int updateCount = investorWalletDao.updateInvestorWallet(wallet);
			if (updateCount <= 0) {
				throw new RuntimeException("下单失败");
			}
			InvestorWalletFlowEntity investorWalletFlow = new InvestorWalletFlowEntity();
			try {
				BeanUtils.copyProperties(investorWalletFlow, wallet);
			} catch (IllegalAccessException | InvocationTargetException e) {
				e.printStackTrace();
			}
			investorWalletFlow.setTransType(TransType.FREEZE_TO_PAYMENT);// 冻结转支付
			investorWalletFlow.setId(null);
			investorWalletFlow.setTransBalance(record.getInvestAmount());
			int walletFlowCount = investorWalletDao.insertInvestorWalletFlow(investorWalletFlow);
			if (walletFlowCount <= 0) {
				throw new RuntimeException("下单失败");
			}
		}
	}

	/**
	 * 钱包流水
	 * 
	 * @param investorWallet 钱包对象
	 * @param investor       投资用户
	 * @param investObject   标的对象
	 * @param investMoney    投资金额
	 */
	private void walletHandle(InvestorWalletEntity investorWallet, InvestorEntity investor,
			InvestObjectEntity investObject, BigDecimal investMoney){
		Date curDate = new Date();
		// 冻结钱包、钱包流水
		BigDecimal curMoney = investorWallet.getCurrentBalance().subtract(investMoney).setScale(2,
				BigDecimal.ROUND_HALF_UP);
		BigDecimal sumVote = investorWallet.getAccumulateVote().add(investMoney).setScale(2, BigDecimal.ROUND_HALF_UP);
		BigDecimal investFrozen = investorWallet.getInvestFrozen().add(investMoney).setScale(2,
				BigDecimal.ROUND_HALF_UP);
		investorWallet.setCurrentBalance(curMoney);
		investorWallet.setInvestFrozen(investFrozen);
		investorWallet.setAccumulateVote(sumVote);
		investorWallet.setUpdateTime(curDate);
		int updateCount = investorWalletDao.updateInvestorWallet(investorWallet);
		if (updateCount <= 0) {
			throw new RuntimeException("下单失败"); // 回滚事物
		}
		InvestorWalletFlowEntity investorWalletFlow = new InvestorWalletFlowEntity();
		try {
			BeanUtils.copyProperties(investorWalletFlow, investorWallet);
		} catch (IllegalAccessException | InvocationTargetException e) {
			e.printStackTrace();
		}
		investorWalletFlow.setTransType(TransType.PAY_FREEZE);
		investorWalletFlow.setId(null);
		investorWalletFlow.setTransBalance(investMoney);
		int walletFlowCount = investorWalletDao.insertInvestorWalletFlow(investorWalletFlow);
		if (walletFlowCount <= 0) {
			throw new RuntimeException("下单失败");
		}
		// 标的记录
		InvestorRecordEntity investorRecord = new InvestorRecordEntity();
		investorRecord.setLoaneeId(investObject.getLoaneeId());
		investorRecord.setInvestorId(investor.getId());
		investorRecord.setObjectId(investObject.getId());
		investorRecord.setInvestAmount(investMoney);
		investorRecord.setCreateTime(curDate);
		investorRecord.setUpdateTime(curDate);
		investorRecord.setInvestorAccount(investor.getAccount());
		investorRecord.setInvestorNickName(investor.getNickname());
		investorRecord.setStatus(InvestorRecordEntity.STATUS_YES);
		BigDecimal rateYield = investObject.getAnnualizedYield();// 年化收益率
		BigDecimal deadline = investObject.getAnnualizedYield();// 期限
		BigDecimal expectAmount = BigDecimalUtils.incomeHandle(investMoney, rateYield, deadline, investObject.getDeadlineType());
		investorRecord.setExpectAmount(expectAmount);
		int addCount = investorDao.insertInvestorRecord(investorRecord);
		if (addCount <= 0) {
			throw new RuntimeException("下单失败");
		}
		
		InvestObjectEntity object=	investObjectManager.findInvestObjectDetail(investObject.getId());
		// 标的已投金额修改
		BigDecimal investedAmount = investObject.getInvestedAmount().add(investMoney).setScale(2,
				BigDecimal.ROUND_HALF_UP);
		investObject.setInvestedAmount(investedAmount);
		object.setInvestedAmount(investedAmount);
		ModelResult<InvestObjExtEntity> ext=	investObjectService.findInvestObjExtEntityDetail(investObject.getId());
		ModelResult<Boolean> modelResult = investObjectService.updateInvestObjectEntity(object,ext.getModel());
		if (!modelResult.isSuccess() || !modelResult.getModel()) {
			throw new RuntimeException("下单失败");
		}
	}

	@Override
	public ModelResult<PageResult<Object[]>> findPageInvestorEntity(InvestorVO vo) {

		ModelResult<PageResult<Object[]>> result = new ModelResult<PageResult<Object[]>>();
		try {
			result.setModel(investorDao.findPageInvestorEntity(vo));
		} catch (Exception e) {
			e.printStackTrace();
			result.withError("投资者信息分页查询：", e.getMessage());
		}
		return result;
	}

	@Override
	public ModelResult<List<Object[]>> getInvestorNameorMobile(String keywords) {

		ModelResult<List<Object[]>> result = new ModelResult<List<Object[]>>();
		try {
			result.setModel(investorDao.getInvestorNameorMobile(keywords));
		} catch (Exception e) {
			e.printStackTrace();
			result.withError("投资者用户名联想查询：", e.getMessage());
		}
		return result;
	}

	@Override
	public ModelResult<Boolean> updateStatus(String id, int status) {

		ModelResult<Boolean> result = new ModelResult<Boolean>();
		try {
			result.setModel(investorDao.updateStatus(id, status));
		} catch (Exception e) {
			e.printStackTrace();
			result.withError("修改投资者状态：", e.getMessage());
		}
		return result;
	}
	
	@Override
	public ModelResult<Boolean> updateInvestor(InvestorEntity investor) {
		ModelResult<Boolean> result = new ModelResult<>();
		try {
			if (investor.getId().isEmpty()) {
				logger.error("修改投资者信息失败，参数为空, investorId:{}", investor.getId());
				return result.withError("InvestorServiceInnerImpl.updateInvestor", "修改投资者信息失败，参数为空");
			}
			Boolean bool = investorDao.updateInvestor(investor);
			result.withModel(bool);
		} catch (Exception e) {
			logger.error("修改投资者信息失败, investorId:{}", investor.getId());
			result.withError("InvestorServiceInnerImpl.updateInvestor", "获取投资者失败");
			e.printStackTrace();
			return result;
		}
		return result;
	}
	
	@Override
	public ModelResult<String> getTradePasswrod(String id){
		ModelResult<String> result = new ModelResult<String>();
		try {
			result.setModel(investorDao.getPasswrod(id));
		} catch (Exception e) {
			e.printStackTrace();
			result.withError("获取密码失败：", e.getMessage());
		}
		return result;
	}

	@Override
	public ModelResult<Boolean> saveTradePasswrod(String id,String password) {
		ModelResult<Boolean> model=new ModelResult<Boolean>();
		try {
			Boolean bool =  investorDao.savePasswrod(id, password);
			model.setModel(bool);	
		} catch (Exception e) {
			logger.error("交易密码保存失败");
			model.withError("InvestorServiceInnerImpl.savePasswrod", "交易密码保存失败");
			e.printStackTrace();
			return model;
		}
		return model;
	}

	@Override
	public ModelResult<Boolean> updateInvestorRecord(InvestorRecordEntity investorRecord) {
		ModelResult<Boolean> result = new ModelResult<>();
		try {
			if (investorRecord.getId().isEmpty()) {
				logger.error("修改用户投资记录失败，参数为空, recordId:{}", investorRecord.getId());
				return result.withError("InvestorServiceInnerImpl.updateInvestorRecord", "修改用户投资记录失败，参数为空");
			}
			Boolean bool = investorDao.updateInvestorRecord(investorRecord);
			result.withModel(bool);
		} catch (Exception e) {
			logger.error("修改用户投资记录失败, recordId:{}", investorRecord.getId());
			result.withError("InvestorServiceInnerImpl.updateInvestorRecord", "修改用户投资记录失败");
			e.printStackTrace();
			return result;
		}
		return result;
	
	}
	
	@Override
	public ModelResult<InvestorEntity> queryInvestorByAccount(String account) {
		ModelResult<InvestorEntity> modelResult = new ModelResult<>();
		try {
			modelResult.withModel(investorDao.queryInvestorByAccount(account));
		} catch (Exception e) {
			e.printStackTrace();
			modelResult.withError("查询用户信息失败：", e.getMessage());
		}
		return modelResult;
	}

}
